#ifndef __IOMANAGER_H__
#define __IOMANAGER_H__

#include "schedule.h"
#include "timer.h"

namespace johnsonli
{
    //异步IO管理类，对epoll封装
    class IOManager : public Scheduler, public TimerManager
    {
    public:
        typedef std::shared_ptr<IOManager> ptr;
        typedef RWMutex MutexType;
        
        //IO事件
        enum Event
        {
            NONE    = 0x0,
            READ    = 0x1,
            WRITE   = 0x4
        };

    public:
        //构造函数
        IOManager(size_t threads = 1, bool use_caller = true, const std::string& name = "");

        ~IOManager();

        /**
         * @brief 添加事件
         * @param[in] fd socket句柄
         * @param[in] event 事件类型
         * @param[in] cb 事件回调函数
         * @return 添加成功返回0,失败返回-1
         */
        int addEvent(int fd, Event event, std::function<void()> cb = nullptr);

        /**
         * @brief 删除事件
         * @param[in] fd socket句柄
         * @param[in] event 事件类型
         * @attention 不会触发事件
         */
        bool delEvent(int fd, Event event);

        /**
         * @brief 取消事件
         * @param[in] fd socket句柄
         * @param[in] event 事件类型
         * @attention 如果事件存在则触发事件
         */
        bool cancelEvent(int fd, Event event);

        /**
         * @brief 取消所有事件
         * @param[in] fd socket句柄
         */
        bool cancelAll(int fd);

        /**
         * @brief 返回当前的IOManager
         */
        static IOManager* GetThis();

    protected:
        void tickle() override;
        bool stopping() override;
        void idle() override;

        void onTimerInsertedAtFront() override;

        /**
         * @brief 重置socket句柄上下文的容器大小
         * @param[in] size 容量大小
         */
        void contextResize(size_t size);

    private:
        //socket fd的上下文类
        struct FdContext
        {
            typedef Mutex MutexType;

            //事件上下文类
            struct EventContext
            {
                Scheduler* scheduler = nullptr;     //事件执行的调度器
                Fiber::ptr fiber;                   //事件协程
                std::function<void()> cb;           //事件的回调函数
            };

            //获取指定事件的上下文
            EventContext& getEventContext(Event event);
            //重置事件的上下文
            void resetEventContext(EventContext& ctx);
            //触发指定的事件(添加到任务协程)
            void triggerEvent(Event event);

            EventContext read;      //读事件上下文
            EventContext write;     //写事件上下文

            int fd = 0;             //事件关联的句柄
            Event events = NONE;    //当前注册的事件
            MutexType mutex;        //事件的mutex
        };

    private:
        int m_epfd;                                     //epoll 文件句柄
        int m_tickleFds[2];                             //pipe 文件句柄，用于通知任务
        std::atomic<size_t> m_pendingEventCount = {0};  //当前等待执行的事件数量
        std::vector<FdContext*> m_fdContexts;           //socket事件上下文的容器
        MutexType m_mutex;
    };
}

#endif 